#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UTable.Objects;
using System.Collections.ObjectModel;
using System.Windows.Threading;
using System.Windows;
using UTable.Objects.Controls;
using UTable.ObjectManager.Commands;

namespace UTable.Input.Text
{
    public class TextInputManager
    {
        Collection<TextInputProvider> _textInputProviders;

        Collection<TextInputProvider> _availableProviders;

        Dictionary<IVisualNode, TextInputProvider> _provideMap = new Dictionary<IVisualNode,TextInputProvider>();

        Dispatcher _dispatcher;

        public TextInputManager()
        {
            _dispatcher = Application.Current.Dispatcher;
            UTableHelper.RegisterInputMapper(typeof(TextInputEventArgs), new TextInputMapper());
        }

        private delegate bool RequestTextInputHandler(IVisualNode node);
        private delegate void TerminateTextInputHandler(IVisualNode node);
        
        private bool OnRequestTextInput(IVisualNode node)
        {
            IObject obj = UTableHelper.GetEntity(node);

            if (obj == null)
                return false;

            IObject container = ObjectTree.GetParent(obj) as IObject;

            if (container == null && node is UObject)
            {
                container = (node as UObject).Entity;
            }
            if (container == null)
                return false;

            if (_provideMap.ContainsKey(node))
                return false;

            VirtualKeyboard keyboard = new VirtualKeyboard();

			// TODO
			// Put the keyboard at the right position
            // Point p = ObjectControlTree.TranslatePoint(node, new Point(0, 0), container);
			Point p = ObjectTree.TranslatePoint(obj, new Point(0, obj.Height), container);
            keyboard.Width = 860;
            keyboard.Height = 330;

            if (node is UObject)
                p = new Point((obj.Width - keyboard.Width) / 2, (obj.Height - keyboard.Height) / 2);

            keyboard.Position = new Point(p.X, p.Y);
            keyboard.Orientation = obj.Orientation;
            keyboard.ScaleX = obj.ScaleX;
            keyboard.ScaleY = obj.ScaleY;
            keyboard.ZIndex = obj.ZIndex + 1;
            UTableHelper.PutCommand(new ObjectCommand(container, ObjectCommandType.Insert, keyboard));
            // UTableHelper.PutCommand(new ObjectCommand(container, ObjectCommandType.Join, new ObjectJoinCommandArgs(obj, keyboard)));
            KeyboardTextInputProvider provider = new KeyboardTextInputProvider(keyboard, "Virtual Keyboard");
            provider.Target = node;
            _provideMap.Add(node, provider);

            UTableHelper.RegisterInputProvider(typeof(TextInputEventArgs), provider);
            
            return false;
        }

        private void OnTerminateTextInput(IVisualNode node)
        {
			IObject obj = UTableHelper.GetEntity(node);

            if (obj == null)
                return;
            if (!_provideMap.ContainsKey(node))
                return;
            IObjectEntity container = ObjectTree.GetParent(obj) as IObjectEntity;
            if (container == null &&  node is UObject)
            {
                container = (node as UObject).Entity;
            }
            if (container == null)
                return;
            IVisualNode keyboard = (_provideMap[node] as KeyboardTextInputProvider).Keyboard as IVisualNode;
            UTableHelper.PutCommand(new ObjectCommand(container, ObjectCommandType.Remove, keyboard));
            UTableHelper.UnregisterInputProvider(typeof(TextInputEventArgs), _provideMap[node]);
            _provideMap.Remove(node);
        }

        public void RegisterTextInputProvider(TextInputProvider provider)
        {

        }

        public void UnRegisterTextInputProvider(TextInputProvider provider)
        {

        }

        public IObjectTree ObjectTree { get; set; }

        public ObjectControlTree ObjectControlTree { get; set; }

        public Collection<TextInputProvider> TextInputProviders
        {
            get
            {
                return _textInputProviders;
            }
        }

        public Collection<TextInputProvider> AvailableTextInputProviders
        {
            get
            {
                return _availableProviders;
            }
        }

        public bool SwithTextInputProvider(IVisualNode node, TextInputProvider provider)
        {
            throw new NotImplementedException();
        }

        public bool RequestTextInput(IVisualNode node)
        {
            return (bool)_dispatcher.Invoke(new RequestTextInputHandler(this.OnRequestTextInput), new object[] {node});
        }

        public void TerminateTextInput(IVisualNode node)
        {
            _dispatcher.BeginInvoke(new TerminateTextInputHandler(this.OnTerminateTextInput), new object[] { node });
        }

        public TextInputProvider GetCurrentTextInputProvider(IInputNode node)
        {
            throw new NotImplementedException();
        }
    }
}
